# -*- coding: utf-8 -*-


def logging_ctx(logger):

    def decorator(fn):
        def wrapper(*args, **kwargs):
            logger.debug('{func} with args: {args}'.format(func=fn.__name__,
                                                           args=args))
            try:
                result = fn(*args, **kwargs)
                logger.debug('{func} result: {result}'.format(
                    func=fn.__name__, result=result))
                return result
            except Exception:
                logger.exception('call failed')
                raise
        return wrapper

    return decorator


def logging_before(logger):

    def decorator(fn):
        def wrapper(*args, **kwargs):
            logger.debug('{func} with args: {args}'.format(func=fn.__name__,
                                                           args=args))
            try:
                result = fn(*args, **kwargs)
                return result
            except Exception:
                logger.exception('call failed')
                raise
        return wrapper

    return decorator


def logging_after(logger):

    def decorator(fn):
        def wrapper(*args, **kwargs):
            try:
                result = fn(*args, **kwargs)
                logger.debug('{func} result: {result}'.format(
                    func=fn.__name__, result=result))
                return result
            except Exception:
                logger.exception('call failed')
                raise
        return wrapper

    return decorator


import time
import hashlib
import pickle

from itertools import chain

cache = {}


def is_obsolete(entry, duration):
    '''判断是否过期'''
    return time.time() - entry['time'] > duration


def compute_key(function, args, kwds):
    '''通过sha1算法生成一个key'''
    key = pickle.dumps((function.func_name, args, kwds))
    return hashlib.sha1(key).hexdigest()


def memorize(duration=10):
    def _memorize(function):
        def __memorize(*args, **kwds):
            key = compute_key(function, args, kwds)
            if (key in cache and not is_obsolete(cache[key], duration)):
                print('cached')
                return cache[key]['value']
            print('missed')
            result = function(*args, **kwds)
            cache[key] = {'value': result, 'time': time.time()}
            return result
        return __memorize
    return _memorize
